
/*
 * Copyright (C) Igor Sysoev
 * Copyright (C) Nginx, Inc.
 */


#ifndef _NGX_HASH_H_INCLUDED_
#define _NGX_HASH_H_INCLUDED_


#include <ngx_config.h>
#include <ngx_core.h>

/*@brief:hash节点的结构定义
 *
 */
typedef struct {
    void             *value;  //ip;
    u_short           len;  //url长度;
    u_char            name[1];  //url;
} ngx_hash_elt_t;

/*
 *@attention:nginx主要用hash来存放url和ip的关系, 
 *@目的是通过url来查找ip.
 */

/*
 *@brief:这类是key中不包含通配符的ngx_hash_t.
 *
 */
typedef struct {
    ngx_hash_elt_t  **buckets; //每个哈希桶的起始地址;
    ngx_uint_t        size;  //桶的个数;
} ngx_hash_t;

/*
 *@brief:这类是key中包含通配符的ngx_hash_wildcard_t,
 *
 */
typedef struct {
    ngx_hash_t        hash;
    void             *value;
} ngx_hash_wildcard_t;


/*
 *@brief:这个结构主要用于初始化hash表的,nginx只能一次性的初始化.
 *
 */
typedef struct {
    ngx_str_t         key; //<key,value>中的key 
    ngx_uint_t        key_hash;  //key通过hash函数计算出来的hash值;
    void             *value; //<key, value>中的value 
} ngx_hash_key_t;


/*
 *@brief:哈希表的哈希函数;
 *
 */
typedef ngx_uint_t (*ngx_hash_key_pt) (u_char *data, size_t len);


/*
 *@brief:用户在配置文件中定义虚拟主机时可能定义包含通配符的url.
 */
typedef struct {
    ngx_hash_t            hash;  //不包括通配符的hash
    ngx_hash_wildcard_t  *wc_head;  //包含前缀通配符的hash
    ngx_hash_wildcard_t  *wc_tail;  //包含后缀通配符的hash 
} ngx_hash_combined_t;


/*
 *@brief:哈希表的管理结构
 *
 */
typedef struct {
    ngx_hash_t       *hash;  //指向待新建的hash表;
    ngx_hash_key_pt   key;  //哈希函数指针;
    ngx_uint_t        max_size; //hash表中桶个数的最大值, 实际桶的个数存放在前面ngx_hash_t中的size字段中.
    ngx_uint_t        bucket_size; //每个桶的大小;

    char             *name;  //hash表名称;
    ngx_pool_t       *pool;  //构建hash所用的内存池;
    ngx_pool_t       *temp_pool;  //临时内存池;
} ngx_hash_init_t;


#define NGX_HASH_SMALL            1
#define NGX_HASH_LARGE            2

#define NGX_HASH_LARGE_ASIZE      16384
#define NGX_HASH_LARGE_HSIZE      10007

#define NGX_HASH_WILDCARD_KEY     1
#define NGX_HASH_READONLY_KEY     2


/*
 *@brief:这个结构存放了初始化hash需要的所有键值对, keys数组用来初始化不包含通配符的hash 
 *		dns_wc_head数组用来初始化包含前缀通配符的hash.(存放的key都是已经去掉通配符的key)
 *		dns_wc_tail数组用来初始化包含后缀通配符的hash.
 */
typedef struct {
    ngx_uint_t        hsize;

    ngx_pool_t       *pool;
    ngx_pool_t       *temp_pool;

    ngx_array_t       keys;
    ngx_array_t      *keys_hash;  //用来检测冲突的;

    ngx_array_t       dns_wc_head;
    ngx_array_t      *dns_wc_head_hash;

    ngx_array_t       dns_wc_tail;
    ngx_array_t      *dns_wc_tail_hash;
} ngx_hash_keys_arrays_t;


/*
 *@该结构用于http报文的头部解析
 *
 */
typedef struct {
    ngx_uint_t        hash;
    ngx_str_t         key;
    ngx_str_t         value;
    u_char           *lowcase_key;
} ngx_table_elt_t;

/*****************************************************************************************************************
 *@brief:接口说明
 ****************************************************************************************************************/
void *ngx_hash_find(ngx_hash_t *hash, ngx_uint_t key, u_char *name, size_t len);
void *ngx_hash_find_wc_head(ngx_hash_wildcard_t *hwc, u_char *name, size_t len);
void *ngx_hash_find_wc_tail(ngx_hash_wildcard_t *hwc, u_char *name, size_t len);
void *ngx_hash_find_combined(ngx_hash_combined_t *hash, ngx_uint_t key, u_char *name, size_t len);

ngx_int_t ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, ngx_uint_t nelts);
ngx_int_t ngx_hash_wildcard_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, ngx_uint_t nelts);

#define ngx_hash(key, c)   ((ngx_uint_t) key * 31 + c)
ngx_uint_t ngx_hash_key(u_char *data, size_t len);
ngx_uint_t ngx_hash_key_lc(u_char *data, size_t len);
ngx_uint_t ngx_hash_strlow(u_char *dst, u_char *src, size_t n);
ngx_int_t ngx_hash_keys_array_init(ngx_hash_keys_arrays_t *ha, ngx_uint_t type);
ngx_int_t ngx_hash_add_key(ngx_hash_keys_arrays_t *ha, ngx_str_t *key,void *value, ngx_uint_t flags);


#endif /* _NGX_HASH_H_INCLUDED_ */
